/*
 * Copyright 2015 Rudson Lima
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package br.liveo.navigationliveo;

import br.liveo.adapter.NavigationLiveoAdapter;
import br.liveo.model.HelpItem;
import br.liveo.model.HelpLiveo;
import br.liveo.model.Navigation;
import br.liveo.ui.RoundedImageView;
import br.liveo.utils.ToastUtil;
import br.liveo.ui.ToolBar;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.*;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;

import ohos.multimodalinput.event.TouchEvent;

import java.util.List;
import java.util.Optional;

/**
 * NavigationLiveo
 */
public abstract class NavigationLiveo extends AbilitySlice {

    /**
     * 状态栏高度
     */
    public Integer statusBarHeight = 0;
    /**
     * 用户名
     */
    public Text userName;
    /**
     * 用户邮箱
     */
    public Text userEmail;
    /**
     * 用户头像
     */
    public RoundedImageView userPhoto;
    /**
     * 用户背景
     */
    public Image userBackground;
    /**
     * 页脚图片
     */
    public Image footerIcon;
    /**
     * 页脚标签
     */
    public Text footerTitle;
    /**
     * mHelpLiveo
     */
    public HelpLiveo mHelpLiveo;
    /**
     * tabList
     */
    public TabList tabList;
    /**
     * pages
     */
    public List<Component> pages;
    /**
     * 状态栏
     */
    public Component statusBar;

    private int width;
    private int dropX;
    private int dropY;
    private int drop1;
    private int drop2;
    private int moveX;
    private int drop3;
    private int drop4;
    private int moveY;
    private int offSet = 1;
    private int windowWith;
    private int windowHeight;
    private int tabIndex = 0;
    private int pageIndex = 0;
    private int listHeaderWith;
    private int mCurrentPosition = 1;
    private float alpha;
    private float tableListHeight;
    private boolean isShowListHeader;

    private Boolean useTable = false;
    private Boolean usePage = true;
    private Navigation mNavigation = new Navigation();
    private ProgressBar myProgressBar;
    private PageSlider myPageSlider;
    private Color darkColor;
    private Color whiteColor;
    private NavigationLiveoAdapter mNavigationAdapter;
    private List<HelpItem> mHelpItem;
    private ListContainer mList;
    private Image leftImageOne;
    private Component listHeader;
    private Component rootComponent;
    private Component.TouchEventListener touchEventListener;
    private Component cptCommonPopupHolder;
    private ToolBar toolBar;
    private Image add;
    private DependentLayout footer;
    private Button addButton;
    private Image more;

    /**
     * intent
     *
     * @param intent intent
     */
    public abstract void onInt(Intent intent);

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_navigation_main);
        initFirst();
        onInt(intent);
        checkTableListAndPageSlider();
        initTable();
        initPageSlider();
        initStatusBar();
        mHelpItem = mHelpLiveo.getHelp();
        setAdapterNavigation();
        setCheckedItemNavigation(mCurrentPosition);
        initTouchEventListener();
        listHeaderWith = listHeader.getWidth();
        tableListHeight = tabList.getHeight() + statusBarHeight + toolBar.getHeight();
        listHeader.setTranslationX(-listHeaderWith);
        rootComponent.setTouchEventListener(touchEventListener);

    }

    private void initStatusBar() {
        if (windowWith > windowHeight) {
            if (statusBarHeight == 0) {
                statusBarHeight = 100;
            }
        }
        statusBar.setHeight(statusBarHeight);
    }

    private void setAdapterNavigation() {
        if (mHelpItem != null) {
            mNavigationAdapter = new NavigationLiveoAdapter(this,
                    NavigationLiveoList.getNavigationAdapter(this,
                            mHelpItem, mNavigation.colorSelected, mNavigation.removeSelector));
        } else {
            mNavigationAdapter = new NavigationLiveoAdapter(this,
                    NavigationLiveoList.getNavigationAdapter(this, mNavigation));
        }
        mList.setItemProvider(mNavigationAdapter);
    }

    /**
     * 设置页脚
     *
     * @param title title
     * @param imageId imageId
     * @return NavigationLiveo
     */
    public NavigationLiveo setFooter(String title, Integer imageId) {
        footerTitle.setText(title);
        footerIcon.setPixelMap(imageId);
        return this;
    }

    private void checkTableListAndPageSlider() {
        Integer tableListSize = tabList.getTabCount();
        Integer pageSize = pages.size();
        if (tableListSize != pageSize) {
            throw new IllegalStateException("Please keep the number of TableList and Page the same");
        }
        if (tableListSize != 3 && pageSize != 3) {
            myProgressBar.setVisibility(Component.HIDE);
        }
    }

    /**
     * init Component
     */
    private void initFirst() {
        rootComponent = findComponentById(ResourceTable.Id_rootComponent);
        cptCommonPopupHolder = findComponentById(ResourceTable.Id_cpt_common_popup_holder);
        statusBar = findComponentById(ResourceTable.Id_statusBar);
        toolBar = (ToolBar) findComponentById(ResourceTable.Id_toolBar);
        tabList = (TabList) findComponentById(br.liveo.navigationliveo.ResourceTable.Id_tab_list);
        listHeader = findComponentById(ResourceTable.Id_listHeader);
        userBackground = (Image) findComponentById(ResourceTable.Id_userBackground);
        userBackground.setClickedListener(component -> closeDrawer());
        userPhoto = (RoundedImageView) findComponentById(ResourceTable.Id_userPhoto);
        userName = (Text) findComponentById(ResourceTable.Id_userName);
        userEmail = (Text) findComponentById(ResourceTable.Id_userEmail);
        footer = (DependentLayout) findComponentById(ResourceTable.Id_footer);
        footerIcon = (Image) findComponentById(ResourceTable.Id_footerIcon);
        footerTitle = (Text) findComponentById(ResourceTable.Id_footerTitle);
        leftImageOne = (Image) findComponentById(ResourceTable.Id_leftImage_one);
        add = (Image) findComponentById(ResourceTable.Id_rightImageTwo_one);
        mList = (ListContainer) this.findComponentById(ResourceTable.Id_container);
        addButton = (Button) findComponentById(ResourceTable.Id_addButton);
        addButton.setTouchEventListener((component, touchEvent) -> {
            ToastUtil.show(this, "Add");
            tabList.setEnabled(false);
            more.setVisibility(Component.VISIBLE);
            more.setEnabled(true);
            addButton.setVisibility(Component.HIDE);
            return false;
        });
        more = (Image) findComponentById(ResourceTable.Id_rightImageTwo_tow);
        mList.setLongClickable(false);
        TableLayoutManager tableLayoutManager = new TableLayoutManager();
        tableLayoutManager.setColumnCount(1);
        tableLayoutManager.setOrientation(Component.HORIZONTAL);
        mList.setLayoutManager(tableLayoutManager);
        mList.setCanAcceptScrollListener((component, i, b) -> false);
        leftImageOne.setClickedListener(component -> {
            AnimatorValue animatorValue = new AnimatorValue();
            animatorValue.setDuration(300);
            animatorValue.setCurveType(Animator.CurveType.PHYSICAL_FLING);
            animatorValue.setValueUpdateListener((animatorValue1, v) -> {
                listHeader.setTranslationX((v - 1F) * listHeaderWith);
                cptCommonPopupHolder.setAlpha(v);
                leftImageOne.setRotation(v * 180);
            });
            animatorValue.start();
        });
        darkColor = new Color(Color.getIntColor("#9fcff9"));
        whiteColor = new Color(Color.getIntColor("#ffffff"));
        Optional<Display>
                display = DisplayManager.getInstance().getDefaultDisplay(this.getContext());
        Point pt = new Point();
        display.get().getSize(pt);
        windowWith = display.get().getAttributes().width;
        windowHeight = display.get().getAttributes().height;
        width = windowWith / 3;
        myPageSlider = (PageSlider) findComponentById(ResourceTable.Id_page_main_slider);
        myProgressBar = (ProgressBar) findComponentById(ResourceTable.Id_myProgressBar);
        if (windowWith > windowHeight) {
            myProgressBar.setWidth(1080);
        } else {
            myProgressBar.setWidth(windowWith);
        }
        myProgressBar.setMaxValue(windowWith);
        myProgressBar.setProgressValue(0);
        myProgressBar.setViceProgress(width);
    }

    /**
     * init TableList
     */
    private void initTable() {
        if (tabList.getTabCount() > 0) {
            tabList.selectTabAt(0);
            tabList.addTabSelectedListener(new TabList.TabSelectedListener() {
                @Override
                public void onSelected(TabList.Tab tab) {
                    tabIndex = tab.getPosition();
                    if (useTable) {
                        myPageSlider.setCurrentPage(tab.getPosition());
                    }
                }

                @Override
                public void onUnselected(TabList.Tab tab) {
                }

                @Override
                public void onReselected(TabList.Tab tab) {
                }
            });
        }
    }

    /**
     * init PageSlider
     */
    private void initPageSlider() {
        myPageSlider.setProvider(new ViewPagerFragment(pages));
        myPageSlider.setPageSwitchTime(500);
        myPageSlider.addPageChangedListener(new PageSlider.PageChangedListener() {
            @Override
            public void onPageSliding(int potion, float v1, int i1) {
                if (tabList.getTabCount() == 3) {
                    // 判断是否用的tableList来选中的
                    if (useTable) {
                        float a1;
                        float b1;
                        if (i1 > 0) {
                            a1 = (tabIndex - 1) * width + i1 / 3;
                            b1 = tabIndex * width + i1 / 3;
                        } else {
                            a1 = (tabIndex + 1) * width + i1 / 3;
                            b1 = (tabIndex + 2) * width + i1 / 3;
                        }
                        myProgressBar.setProgressValue((int) a1);
                        myProgressBar.setViceProgress((int) b1);
                    } else {
                        if (offSet == 1 && usePage) {
                            if (Math.abs(i1) / 3 > width / 2 && i1 > 0) {
                                tabList.getTabAt(potion + 1).setTextColor(whiteColor);
                                tabList.getTabAt(potion).setTextColor(darkColor);
                            } else if ((Math.abs(i1) / 3 < width / 2 && i1 > 0 && potion == 2)) {
                                tabList.getTabAt(potion).setTextColor(whiteColor);
                            } else {
                                if ((Math.abs(i1) / 3 < width / 2 && i1 > 0)) {
                                    tabList.getTabAt(potion + 1).setTextColor(darkColor);
                                    tabList.getTabAt(potion).setTextColor(whiteColor);
                                }
                            }
                            if (Math.abs(i1) / 3 > width / 2 && i1 < 0 && potion > 0) {
                                tabList.getTabAt(potion - 1).setTextColor(whiteColor);
                                tabList.getTabAt(potion).setTextColor(darkColor);
                            } else if (Math.abs(i1) / 3 < width / 2 && i1 < 0 && potion == 0) {
                                tabList.getTabAt(potion).setTextColor(whiteColor);
                            } else {
                                if ((Math.abs(i1) / 3 < width / 2 && i1 < 0)) {
                                    tabList.getTabAt(potion - 1).setTextColor(darkColor);
                                    tabList.getTabAt(potion).setTextColor(whiteColor);
                                }
                            }
                            float a1 = potion * width + i1 / 3;
                            float b1 = (potion + 1) * width + i1 / 3;
                            myProgressBar.setProgressValue((int) a1);
                            myProgressBar.setViceProgress((int) b1);
                        }
                    }
                }
            }

            @Override
            public void onPageSlideStateChanged(int i1) {
            }

            @Override
            public void onPageChosen(int i1) {
                if (tabList.getTabCount() >= i1 + 1) {
                    tabList.selectTabAt(i1);
                }
            }
        });
    }

    @Override
    protected void onBackPressed() {
        if (toolBar.getToolBarOne()) {
            super.onBackPressed();
        } else {
            toolBar.toolBarTow.setVisibility(Component.HIDE);
            toolBar.toolBarOne.setVisibility(Component.VISIBLE);
            toolBar.setToolBarOne(true);
        }
    }

    /**
     * init touchEventListener
     */
    private void initTouchEventListener() {
        touchEventListener = (component, touchEvent) -> {
            int touchEventAction = touchEvent.getAction();
            // 判断more按钮的addButton是否存在，做一个类似于dialog点击空白消失的效果
            if (addButton.getVisibility() == Component.VISIBLE) {
                tabList.setEnabled(false);
                more.setVisibility(Component.VISIBLE);
                more.setEnabled(true);
                addButton.setVisibility(Component.HIDE);
            } else {
                switch (touchEventAction) {
                    case TouchEvent.PRIMARY_POINT_DOWN:
                        dropX = (int) touchEvent.getPointerPosition(touchEvent.getIndex()).getX() - component.getLeft();
                        drop1 = dropX;
                        dropY = (int) touchEvent.getPointerPosition(touchEvent.getIndex()).getY() - component.getTop();
                        drop3 = dropY;
                        // 因为上方有关闭的操作,所以将tableList打开
                        tabList.setEnabled(true);
                        // 判断按下的位置是否在tableList上,否则的话就判断按在了PageSlider上
                        if (dropY < tableListHeight) {
                            useTable = true;
                            usePage = false;
                        } else {
                            useTable = false;
                            usePage = true;
                        }
                        // 判断按下的位置是否小于左边距80或者当前的遮蔽层的透明度为1(为1说明listHeader为显示状态),
                        // 然后就关闭myPageSlider的滑动
                        if (dropX < 80 || cptCommonPopupHolder.getAlpha() == 1) {
                            isShowListHeader = true;
                            myPageSlider.setSlidingPossible(false);
                        }
                        // 判断按下的位置是否大于左边距80或者当前的遮蔽层的透明度为0(为0说明listHeader为关闭状态),
                        // 然后就打开myPageSlider的滑动
                        if (dropX > 80 && cptCommonPopupHolder.getAlpha() == 0) {
                            myPageSlider.setSlidingPossible(true);
                        }
                        break;
                    case TouchEvent.POINT_MOVE:
                        // 先判断当先是否想要通过滑动来显示ListHeader
                        if (isShowListHeader) {
                            drop2 = (int) touchEvent.getPointerPosition(touchEvent.getIndex()).getX()
                                    - component.getLeft();
                            drop4 = (int) (touchEvent.getPointerPosition(touchEvent.getIndex()).getY()
                                    - component.getTop());
                            // 现在的位置减去按下的位置计算出偏移量moveX
                            moveX = drop2 - drop1;
                            moveY = drop4 - drop3;
                            if (Math.abs(moveX) > Math.abs(moveY)) {
                                float currentPosition = listHeader.getTranslationX();
                                // 当前位置加上偏移量来算出想要移动到的位置
                                float moveTo = currentPosition + moveX;
                                // TranslationX为0 listHeader的边界，当要移动到的位置大于0时，直接set到0
                                if (moveTo > 0) {
                                    listHeader.setTranslationX(0);
                                } else {
                                    listHeader.setTranslationX(moveTo);
                                }
                                // 计算遮蔽层的透明度
                                alpha = 1 - ((-currentPosition) / (float) listHeaderWith);
                                cptCommonPopupHolder.setAlpha(alpha);
                                // 为了和原库的效果一致 三横按钮旋转
                                leftImageOne.setRotation(alpha * 180);
                            }
                            // 交换当前位置,准备计算下一次的偏移量
                            drop1 = drop2;
                            drop3 = drop4;
                        }
                        break;
                    case TouchEvent.CANCEL:
                    case TouchEvent.PRIMARY_POINT_UP:
                        float translationX = listHeader.getTranslationX();
                        float offSet = cptCommonPopupHolder.getAlpha();
                        // 当抬起手指时判断当前listHeader位置偏左还是偏右，来触发弹出还是收回的动画
                        if (Math.abs(listHeader.getTranslationX()) < listHeaderWith / 2) {
                            AnimatorValue animatorValue = new AnimatorValue();
                            animatorValue.setDuration(300);
                            animatorValue.setCurveType(Animator.CurveType.PHYSICAL_FLING);
                            animatorValue.setValueUpdateListener((animatorValue1, v1) -> {
                                listHeader.setTranslationX((v1 - 1F) * (-translationX));
                                cptCommonPopupHolder.setAlpha(1 - (1 - offSet) * (1 - v1));
                                leftImageOne.setRotation((1 - (1 - offSet) * (1 - v1)) * 180);
                            });
                            animatorValue.start();
                        } else {
                            AnimatorValue animatorValue = new AnimatorValue();
                            animatorValue.setDuration(300);
                            animatorValue.setCurveType(Animator.CurveType.PHYSICAL_FLING);
                            animatorValue.setValueUpdateListener((animatorValue1, v1) -> {
                                listHeader.setTranslationX((1 - v1) * (listHeaderWith + translationX) - listHeaderWith);
                                cptCommonPopupHolder.setAlpha(((1 - v1) * offSet));
                                leftImageOne.setRotation((((1 - v1) * offSet)) * 180);
                            });
                            animatorValue.start();
                        }
                        // 如果按下的位置大于listHeader的宽的话，说明落点在listHeader的外面，直接收回listHeader
                        if (dropX > listHeaderWith && cptCommonPopupHolder.getAlpha() == 1) {
                            closeDrawer();
                        }
                        // 置为false,下次落下的时候在判断
                        isShowListHeader = false;
                        break;
                    default:
                }
            }
            return true;
        };
    }

    /**
     * Close navigation
     */
    public void closeDrawer() {
        if (cptCommonPopupHolder.getAlpha() == 0) {
            return;
        }
        AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setDuration(300);
        animatorValue.setCurveType(Animator.CurveType.PHYSICAL_FLING);
        animatorValue.setValueUpdateListener((animatorValue1, v) -> {
            listHeader.setTranslationX(v * (-listHeaderWith));
            cptCommonPopupHolder.setAlpha(1 - v);
            leftImageOne.setRotation((1 - v) * 180);
        });
        animatorValue.start();
    }

    /**
     * Starting listener navigation
     *
     * @param listener listener.
     * @return NavigationLiveo
     */
    public NavigationLiveo with(ListContainer.ItemClickedListener listener) {
        this.mList.setItemClickedListener(listener);
        return this;
    }

    /**
     * Item color selected in the list - name, icon and counter
     *
     * @param colorId color id.
     * @return NavigationLiveo
     */
    public NavigationLiveo colorItemSelected(int colorId) {
        mNavigation.colorSelected = colorId;
        return this;
    }

    /**
     * 点击侧滑栏的item
     *
     * @param position position
     * @throws RuntimeException You must start the .build(); in onInit() from your main Activity.
     */
    public void setCheckedItemNavigation(int position) {
        if (this.mNavigationAdapter == null) {
            throw new RuntimeException("You must start the .build(); in onInit() from your main Activity.");
        }
        // 判断是否可以选中
        if (mHelpItem.get(position).isCheck()) {
            this.mNavigationAdapter.resetarCheck();
            this.mNavigationAdapter.setChecked(position, true);
        }
        // 判断当先的pages是否为1，是的话就把tableList和ProgressBar隐藏起来
        if (pages.size() == 1) {
            myPageSlider.setProvider(new ViewPagerFragment(pages));
            tabList.setVisibility(Component.HIDE);
            myProgressBar.setVisibility(Component.HIDE);
        } else {
            if (pages.size() == 3) {
                // tableList和ProgressBar显示
                tabList.setVisibility(Component.VISIBLE);
                myProgressBar.setVisibility(Component.VISIBLE);
                myPageSlider.setProvider(new ViewPagerFragment(pages));
                // 因为直接setCurrentPage到0 不能跳转到page0所以只能一步一步移过去
                myPageSlider.setCurrentPage(1);
                myPageSlider.setCurrentPage(0);
                // 为了避免触发usePage的滑动简体，所以全部置为false
                usePage = false;
                useTable = false;
                // 设置progressBar的值为初始状态
                myProgressBar.setProgressValue(0);
                myProgressBar.setViceProgress(width);
            }
        }
        if (mHelpItem.get(position).getIcon() != 0) {
            closeDrawer();
        }
    }

    /**
     * setAddListener
     *
     * @param onClickListener setAddListener
     * @return NavigationLiveo
     */
    public NavigationLiveo setAddListener(Component.ClickedListener onClickListener) {
        add.setClickedListener(onClickListener);
        return this;
    }

    /**
     * setOnClickFooter
     *
     * @param onClickListener onClickListener
     * @return NavigationLiveo
     */
    public NavigationLiveo setOnClickFooter(Component.ClickedListener onClickListener) {
        footer.setClickedListener(onClickListener);
        return this;
    }

    /**
     * 设置UserPhotoListener监听
     *
     * @param onClickListener onClickListener
     * @return NavigationLiveo
     */
    public NavigationLiveo setUserPhotoListener(Component.ClickedListener onClickListener) {
        userPhoto.setClickedListener(onClickListener);
        return this;
    }

    /**
     * First item of the position selected from the list
     *
     * @param position 位置
     * @return NavigationLiveo
     */
    public NavigationLiveo startingPosition(int position) {
        this.mCurrentPosition = position;
        return this;
    }

    /**
     * 设置toolBar的隐藏开关
     *
     * @param componentVisibility 是否隐藏
     * @return NavigationLiveo
     */
    public NavigationLiveo setToolBarVisibility(int componentVisibility) {
        toolBar.setVisibility(componentVisibility);
        return this;
    }
}
